<?php

declare (strict_types=1);

namespace app\admin\model\admin;


use app\common\model\admin\User as UserModel;
use app\admin\service\admin\Auth as AuthService;
use app\admin\model\admin\UserRole;

use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;
use think\Paginator;

/**
 * 后台管理员用户模型
 */
class User extends UserModel
{
    /**
     * 隐藏的字段
     * @var array
     */
    protected $hidden = [
        'password',
    ];

    // 用户登录token
    private mixed $token;

    /**
     * 用户登录
     * @param array $data
     * @return array|bool|null|Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function login(array $data): bool|array|Model|null
    {
        // 验证用户名密码是否正确
        if (!$userInfo = $this->getUserInfoByLogin($data)) {
            return false;
        }
        // 记录登录状态, 并记录token
        $this->token = (new AuthService)->login($userInfo->toArray());
        return $userInfo;
    }

    /**
     * 返回生成的token
     * @return mixed
     */
    public function getToken(): mixed
    {
        return $this->token;
    }

    /**
     * 获取登录用户信息
     * @param array $data
     * @return array|bool|null|Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function getUserInfoByLogin(array $data): bool|array|Model|null
    {
        $where = [];
        $where[] = ['user_name', '=', trim($data['username'])];
        $where[] = ['is_delete', '=', 0];
        // 用户信息
        $useInfo = $this->where($where)->find();
        if (empty($useInfo)) {
            $this->error = '登录失败, 该用户不存在或已删除';
            return false;
        }
        // 验证密码是否正确
        if (!password_verify($data['password'], $useInfo['password'])) {
            $this->error = '登录失败, 用户名或密码错误';
            return false;
        }
        return $useInfo;
    }

    /**
     * 获取用户列表
     * @param array $param
     * @return Paginator
     * @throws DbException
     */
    public function getList(array $param = []): Paginator
    {
        // 查询模型
        $query = $this->getNewQuery();
        // 查询参数
        $params = $this->setQueryDefaultValue($param, ['search' => '']);
        // 关键词搜索
        !empty($params['search']) && $query->where('user_name|real_name', 'like', "%{$params['search']}%");
        // 显示条数
        $limit = $params['limit']?$params['limit']:10;
        // 查询列表记录
        $list = $query->with(['role'])
            ->where('is_delete', '=', '0')
            ->order(['sort' => 'asc', 'create_time' => 'desc'])
            ->paginate($limit);
        // 整理所有角色id
        foreach ($list as &$item) {
            $item['roles'] = getArrayColumn($item['role'], 'role_id');
        }
        return $list;
    }

    /**
     * 新增记录
     * @param array $data
     * @return bool
     */
    public function add(array $data): bool
    {
        $data['user_name'] = strtolower($data['user_name']);
        if (self::checkExist($data['user_name'])) {
            $this->error = '用户名已存在';
            return false;
        }
        if ($data['password'] !== $data['password_confirm']) {
            $this->error = '确认密码不正确';
            return false;
        }
        if (empty($data['roles'])) {
            $this->error = '请选择所属角色';
            return false;
        }
        // 整理数据
        $data['password'] = password_hash($data['password'],PASSWORD_DEFAULT);
        $data['is_super'] = 0;
        $data['create_time'] = time();
        $data['update_time'] = time();
        // 事务处理
        $this->transaction(function () use ($data) {
            // 新增管理员记录
            $this->save($data);
            // 新增角色关系记录
            UserRole::increased((int)$this['user_id'], $data['roles']);
        });
        return true;
    }

    /**
     * 更新记录
     * @param array $data
     * @return bool
     */
    public function edit(array $data): bool
    {
        $data['user_name'] = strtolower($data['user_name']);
        if ($this['user_name'] !== $data['user_name']
            && self::checkExist($data['user_name'])) {
            $this->error = '用户名已存在';
            return false;
        }
        if (!empty($data['password']) && ($data['password'] !== $data['password_confirm'])) {
            $this->error = '确认密码不正确';
            return false;
        }
        if (empty($data['roles']) && !$this['is_super']) {
            $this->error = '请选择所属角色';
            return false;
        }
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'],PASSWORD_DEFAULT);
        } else {
            unset($data['password']);
        }
        $data['update_time'] = time();
        $this->transaction(function () use ($data) {
            // 更新管理员记录
            $this->save($data);
            // 更新角色关系记录
            !$this['is_super'] && UserRole::updates((int)$this['user_id'], $data['roles']);
        });
        return true;
    }

    /**
     * 软删除
     * @return false|int
     */
    public function setDelete(): bool|int
    {
        if ($this['user_id'] == 3) {
            $this->error = '超级管理员不允许删除';
            return false;
        }
        return $this->transaction(function () {
            // 删除对应的角色关系
            UserRole::setDeleteAll([['user_id', '=',$this['user_id']]]);
            return $this->save(['is_delete' => 1]);
        });
    }

    /**
     * 更新当前管理员信息
     * @param array $data
     * @return bool
     */
    public function renew(array $data): bool
    {
        if (!empty($data['password']) && ($data['password'] !== $data['password_confirm'])) {
            $this->error = '确认密码不正确';
            return false;
        }
        if ($this['user_name'] !== $data['user_name']
            && self::checkExist($data['user_name'])) {
            $this->error = '用户名已存在';
            return false;
        }
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'],PASSWORD_DEFAULT);
        }else{
            unset($data['password']);
        }
        unset($data['password_confirm']);
        // 更新管理员信息
        if ($this->save($data) === false) {
            return false;
        }
        // 更新登录状态
        (new AuthService)->update($this->toArray());
        return true;
    }

}
